using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BillsDomain.Properties;

namespace BillsDomain
{
    /// <summary>
    /// 
    /// </summary>
    public class PaymentType : IEquatable<PaymentType>
    {
        /// <summary>
        /// 
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Type is immutable")]
        public static readonly PaymentType Debit = new PaymentType(Resources.Debit);

        /// <summary>
        /// 
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Type is immutable")]
        public static readonly PaymentType Credit = new PaymentType(Resources.Credit);

        /// <summary>
        /// 
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Type is immutable")]
        public static readonly PaymentType Unknown = new PaymentType(Resources.Unknown);

        private readonly static IDictionary<string, PaymentType> AllPaymentTypes = new Dictionary<string, PaymentType>() { { Debit.Name, Debit }, { Credit.Name, Credit }, { Unknown.Name, Unknown } };

        /// <summary>
        /// Initializes a new instance of the <see cref="PaymentType"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        private PaymentType(string name)
        {
            this.Name = name;
        }

        /// <summary>
        /// Finds the name of the by.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns>The PaymentType instance with the given name, or the Unknown instance if the name is not found.</returns>
        public static PaymentType FindByName(string name)
        {
            try
            {
                return AllPaymentTypes[name];
            }
            catch (KeyNotFoundException)
            {
                return Unknown;
            }
        }

        /// <summary>
        /// Returns a <see cref="System.String"/> that represents this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/> that represents this instance.
        /// </returns>
        public override string ToString()
        {
            return this.Name;
        }

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name.</value>
        public string Name { get; private set; }

        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public override int GetHashCode()
        {
            return this.Name.GetHashCode();
        }

        /// <summary>
        /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
        /// <returns>
        /// 	<c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        public override bool Equals(object obj)
        {
            return Equals(obj as PaymentType);
        }

        /// <summary>
        /// Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <param name="other">An object to compare with this object.</param>
        /// <returns><c>true</c> if the current object is equal to the other parameter; otherwise, <c>false</c>.</returns>
        public bool Equals(PaymentType other)
        {
            return (other == null ? false : IsEqualTo(other));
        }

        /// <summary>
        /// Determines whether the current object's reference or Name property is equal to another object's reference or Name property.
        /// </summary>
        /// <param name="other">An object to compare with this object.</param>
        /// <returns>
        /// 	<c>true</c> if the current object's reference or Name property is equal to the other parameter; otherwise, <c>false</c>.
        /// </returns>
        private bool IsEqualTo(PaymentType other)
        {
            return other == this || this.Name.Equals(other.Name);
        }

    }
}
